package com.zx.frpc.utils;


import com.alibaba.fastjson.JSONObject;
import com.zx.frpc.model.Common;
import com.zx.frpc.model.Http;
import lombok.Data;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 说明：ini文件读写操作工具类
 * 作者：FH Admin
 * 官网：www.fhadmin.org
 */
@Data
public class ConfigurationFile {



        private HashMap sections ;
        private transient String currentSecion;
        private transient Properties current;

            /**
             * 构造函数
             * @param filename
             * @throws IOException
             */
            public void IniReader(String filename) throws IOException {
                BufferedReader reader = new BufferedReader(new FileReader(filename));
                read(reader);
                reader.close();
            }
            /**
             * 读取文件
             * @param reader
             * @throws IOException
             */
            protected void read(BufferedReader reader) throws IOException {
                String line;
                while ((line = reader.readLine()) != null) {
                    parseLine(line);
                }
            }

            /**
             * 解析配置文件行
             * @param line
             */
            @SuppressWarnings("unchecked")
            protected void parseLine(String line) {
                line = line.trim();
                if (line.matches("\\[.*\\]")) {
                    currentSecion = line.replaceFirst("\\[(.*)\\]", "$1");
                    current = new Properties();
                    sections.put(currentSecion, current);
                } else if (line.matches(".*=.*")) {
                    if (current != null) {
                        int i = line.indexOf('=');
                        String name = line.substring(0, i);
                        String value = line.substring(i + 1);
                        current.setProperty(name, value);
                    }
                }
            }
            /**
             * 获取值
             * @param section
             * @param name
             * @return
             */
            public String getValue(String section, String name) {
                Properties p = (Properties) sections.get(section);
                if (p == null) {
                    return null;
                }
                String value = p.getProperty(name);
                return value;
            }
            /**
             * 是否包含key
             * @param section
             * @param key
             * @return
             */
            public boolean containsKey(String section,String key) {
                Properties p = (Properties) sections.get(section);
                return p.contains(key);
            }
    /**
     * 从ini配置文件中读取变量的值
     *
     * @param file         配置文件的路径
     * @param section      要获取的变量所在段名称
     * @param variable     要获取的变量名称
     * @param defaultValue 变量名称不存在时的默认值
     * @return 变量的值
     * @throws IOException 抛出文件操作可能出现的io异常
     */

    public static String readCfgValue(String file, String section, String variable, String defaultValue) throws IOException {
        String strLine, value = "";
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        boolean isInSection = false;
        try {
            while ((strLine = bufferedReader.readLine()) != null) {
                strLine = strLine.trim();
                strLine = strLine.split("[;]")[0];
                Pattern p;
                Matcher m;
                p = Pattern.compile("\\[\\w+]");// Pattern.compile("file://[//s*.*//s*//]");
                m = p.matcher((strLine));
                if (m.matches()) {
                    p = Pattern.compile("\\[" + section + "\\]");// Pattern.compile("file://[//s*" + section +
// "file://s*//]");
                    m = p.matcher(strLine);
                    if (m.matches()) {
                        isInSection = true;
                    } else {
                        isInSection = false;
                    }
                }
                if (isInSection == true) {
                    strLine = strLine.trim();
                    String[] strArray = strLine.split("=");
                    if (strArray.length == 1) {
                        value = strArray[0].trim();
                        if (value.equalsIgnoreCase(variable)) {
                            value = "";
                            return value;
                        }
                    } else if (strArray.length == 2) {
                        value = strArray[0].trim();
                        if (value.equalsIgnoreCase(variable)) {
                            value = strArray[1].trim();
                            return value;
                        }
                    } else if (strArray.length > 2) {
                        value = strArray[0].trim();
                        if (value.equalsIgnoreCase(variable)) {
                            value = strLine.substring(strLine.indexOf("=") + 1).trim();
                            return value;
                        }
                    }
                }
            }
        } finally {
            bufferedReader.close();
        }
        return defaultValue;
    }

    /**
     * 修改ini配置文件中变量的值
     *
     * @param file     配置文件的路径
     * @param section  要修改的变量所在段名称
     * @param variable 要修改的变量名称
     * @param value    变量的新值
     * @throws IOException 抛出文件操作可能出现的io异常
     */

    public static boolean writeCfgValue(String file, String section, String variable, String value) throws IOException {
        String fileContent, allLine, strLine, newLine;
        String getValue = null;
        BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
        boolean isInSection = false;
        boolean canAdd = true;
        fileContent = "";
        try {
            while ((allLine = bufferedReader.readLine()) != null) {
                allLine = allLine.trim();
                strLine = allLine.split(";")[0];
                Pattern p;
                Matcher m;
                p = Pattern.compile("\\[\\w+]");
                m = p.matcher((strLine));
                if (m.matches()) {
                    p = Pattern.compile("\\[" + section + "\\]");
                    m = p.matcher(strLine);
                    if (m.matches()) {
                        isInSection = true;
                    } else {
                        isInSection = false;
                    }
                }
                if (isInSection == true) {
                    strLine = strLine.trim();
                    String[] strArray = strLine.split("=");
                    getValue = strArray[0].trim();
                    if (getValue.equalsIgnoreCase(variable)) {
                        newLine = getValue + "=" + value;
                        fileContent += newLine;
                        while ((allLine = bufferedReader.readLine()) != null) {
                            fileContent += "\r\n" + allLine;
                        }
                        bufferedReader.close();
                        canAdd = false;
                        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, false));
                        bufferedWriter.write(fileContent);
                        bufferedWriter.flush();
                        bufferedWriter.close();
                        return true;
                    }
                }
                fileContent += allLine + "\r\n";
            }

            if (canAdd) {
                String str = variable + "=" + value;
                fileContent += str + "\r\n";
                BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, false));
                bufferedWriter.write(fileContent);
                bufferedWriter.flush();
                bufferedWriter.close();
            }
        } catch (IOException ex) {
            throw ex;
        } finally {
            bufferedReader.close();
        }
        return false;
    }
    /**
     * 写入配置
     * @param filename 文件名称
     * @param section 模块名称
     * @param key 键
     * @param value 值
     * @throws IOException
     */
    public static void write(String filename,String section,String key,String value) throws IOException {
        List<String> lines = getLines(filename);
        int sectionIndex = hasSection(lines,section);
        try(BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filename))) {
            if (sectionIndex>-1) {
                Integer[] integers = getKeyIndex(lines,section,key);
                int size = lines.size();
                if (integers == null||integers.length==0) {
                    int addIndex=getWriteIndex(lines,section);//sectionIndex+1;
                    if(addIndex>=size){
                        lines.add(String.format("%s=%s", key, value));
                    }else{
                        lines.add(addIndex,String.format("%s=%s", key, value));
                    }
                } else {
                    String line = null;
                    String valueRegex = "=.*";
                    for (Integer index:integers) {
                        line = lines.remove(index.intValue());
                        line = line.replaceFirst(valueRegex,String.format("=%s",value));
                        lines.add(index.intValue(),line);
                    }
                }
            } else {
                int size = lines.size();
                lines.add(size++,String.format("[%s]", section));
                lines.add(size++,String.format("%s=%s", key, value));
            }
            bufferedWriter.write(lines.get(0));
            for (int i = 1; i < lines.size(); i++) {
                bufferedWriter.newLine();
                bufferedWriter.write(lines.get(i));
            }
        }
    }
    /**
     * 查看配置文件中是否存在section模块
     * @param lines
     * @param section
     * @return -1或模块第一个所在行下标
     * @throws IOException
     */
    private static int hasSection(List<String> lines,String section) throws IOException {
        String sectionLineRegex = "\\[.*\\]", sectionRegex = String.format("\\[%s\\]", section);
        int sectionIndex = -1, currentIndex = 0;
        for (String line:lines) {
            line = StringUtils.trimToEmpty(line);
            if (line.matches(sectionLineRegex)) {
                if (line.matches(sectionRegex)) {
                    sectionIndex = currentIndex;
                    break;
                }
            }
            currentIndex++;
        }
        return sectionIndex;
    }
    /**
     * 获取配置文件中所有行
     * @param filename
     * @return
     * @throws IOException
     */
    private static List<String> getLines(String filename) throws IOException {
        List<String> lines = new ArrayList<>();
        File file =new File(filename);
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader(file))){
            String line = null;
            while ((line=bufferedReader.readLine())!=null){
                lines.add(StringUtils.trimToEmpty(line));
            }
            return lines;
        }
    }
    /**
     * 获取key值的行下标
     * @param lines
     * @param section
     * @param key
     * @return
     * @throws IOException
     */
    private static Integer[] getKeyIndex(List<String> lines, String section, String key) throws IOException {
        List<Integer> keyIndex = new ArrayList<>();
        String value = null;
        int index = 0, currentIndex = 0;
        String sectionLineRegex = "\\[.*\\]", sectionRegex = String.format("\\[%s\\]", section);
        String keyLineRegex = String.format("%s\\s*=\\s*.*", key), keyRegex = String.format("%s\\s*=\\s*", key);
        boolean active = false;
        for (String line:lines) {
            if (line.matches(sectionLineRegex)) {
                if (line.matches(sectionRegex)) {
                    active = true;
                } else {
                    active = false;
                }
            }
            if (active && line.matches(keyLineRegex)) {
                index = currentIndex;
                keyIndex.add(index);
            }
            currentIndex++;
        }
        Integer[] ints = new Integer[keyIndex.size()];
        keyIndex.toArray(ints);
        return ints;
    }

    /**
     * 获取写入行下标
     * @param lines
     * @param section
     * @return
     */
    private static int getWriteIndex(List<String> lines,String section){
        int writeIndex = -1;
        boolean active = false;
        String sectionLineRegex = "\\[.*\\]",sectionRegex = String.format("\\[%s\\]", section);
        for (int i=0;i<lines.size();i++) {
            if(lines.get(i).matches(sectionRegex)){
                active=true;
            }else if(active&&lines.get(i).matches(sectionRegex)){
                writeIndex = i;
                break;
            }
        }
        return writeIndex==-1?lines.size():writeIndex;
    }

    public static void main(String[] args) {
        try {
                    /*;文件事例

                    [Client]

                    ;客户端版本号

                    version=0001

                    ;设备号

                    devNum=6405*/
            String path = System.getProperty("user.dir");
            path = path + "/frpc.ini";

/*            Common common = new Common();

            Field[] declaredFields = common.getClass().getDeclaredFields();
            String defaultValue = "未设置";
            for (Field declaredField : declaredFields) {
                System.err.println(declaredField.getName());
                String name = declaredField.getName();
                if("serialVersionUID".equals(name))continue;
                String value = ConfigurationFile.readCfgValue(path, "common", name, defaultValue);
                if(defaultValue.equals(value)) value = ConfigurationFile.readCfgValue(path, "ssh", name, defaultValue);
                declaredField.setAccessible(true);
                declaredField.set(common,value);
            }
            System.err.println(common);*/
            //ConfigurationFile.write(path,"FFWY_admin","type","http11");
            ConfigurationFile configurationFile = new ConfigurationFile();
            configurationFile.IniReader(path);
            System.err.println(configurationFile.sections);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(configurationFile.sections));
            for (String section : jsonObject.keySet()) {
                if(!"common".equals(section) & !"ssh".equals(section)){
                    Http http = jsonObject.getObject(section, Http.class);
                    http.setSection(section);
                    System.err.println(http);

                }
            }
        } catch (Exception  e) {
            e.printStackTrace();

        }

    }

}